﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Web;

namespace G.Service.Push.Win8
{


    public class SendContext : ISendContext, IDisposable
    {
        [DataContract]
        internal class OAuthToken
        {
            [DataMember(Name = "access_token")]
            public string AccessToken { get; set; }
            [DataMember(Name = "token_type")]
            public string TokenType { get; set; }
        }

        OAuthToken accessToken;
        Queue<INotificationContent> queue;
        private string secret;
        private string sid;
        public SendContext(string secret, string sid, INotificationContent[] contents)
        {
            queue = new Queue<INotificationContent>();
            this.secret = secret;
            this.sid = sid;
            foreach (var item in contents)
                queue.Enqueue(item);
        }

        public void Send()
        {
            try
            {
                accessToken = GetAccessToken(secret, sid);
            }
            catch (Exception ex)
            {
                if (SendException != null)
                    SendException(this, new SendExceptionArgs(new Exception("获取oAuthToken出错", ex)));
            }

            while (queue.Count > 0)
            {
                var content = queue.Dequeue();
                System.Threading.ThreadPool.QueueUserWorkItem(PostToWns, content);
            }
        }

        private void PostToWns(object p)
        {
            INotificationContent content = p as INotificationContent;
            try
            {
                byte[] contentInBytes = Encoding.UTF8.GetBytes(content.GetContent());
                HttpWebRequest request = HttpWebRequest.Create(content.Url) as HttpWebRequest;
                request.Method = "POST";
                string type = string.Empty;
                if (content is ToastContent.IToastNotificationContent)
                    type = "wns/toast";
                else if (content is TileContent.ITileNotificationContent)
                    type = "wns/tile";
                else if (content is BadgeContent.IBadgeNotificationContent)
                    type = "wns/badge";
                else
                {
                    //if (SendException != null)
                    //{
                    //    SendException(this, new SendExceptionArgs(new Exception("不支持该NotificationContent")));
                    //}
                    Console.WriteLine("不支持该NotificationContent");
                    return;
                }
                request.Headers.Add("X-WNS-Type", type);
                request.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken.AccessToken));
                //request.BeginGetRequestStream((i) =>
                //{
                //    try
                //    {
                //        Stream requestStream = request.EndGetRequestStream(i);
                //        request.BeginGetResponse((_i) =>
                //        {
                //            using (HttpWebResponse webResponse = (HttpWebResponse)request.EndGetResponse(_i))
                //            {
                //                string code = webResponse.StatusCode.ToString();
                //                Console.WriteLine("发送状态：" + code);
                //            }
                //        }, null);
                //    }
                //    catch (Exception ex)
                //    {
                //        Console.WriteLine("EXCEPTION: " + ex.Message);
                //    }
                //}, null);
                using (Stream requestStream = request.GetRequestStream())
                    requestStream.Write(contentInBytes, 0, contentInBytes.Length);
                using (HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse())
                {
                    string code = webResponse.StatusCode.ToString();
                    Console.WriteLine("发送状态：" + code);
                }
            }
            //catch (WebException webException)
            //{
            //    string exceptionDetails = webException.Response.Headers["WWW-Authenticate"];
            //    if (exceptionDetails.Contains("Token expired"))
            //    {
            //        GetAccessToken(secret, sid);
            //        // Implement a maximum retry policy
            //        return PostToWns(content);
            //    }
            //    else
            //    {
            //        // Log the response
            //        return "EXCEPTION: " + webException.Message;
            //    }
            //}
            catch (Exception ex)
            {
                Console.WriteLine("EXCEPTION: " + ex.Message);
                //return "EXCEPTION: " + ex.Message;
            }
        }

        private OAuthToken GetOAuthTokenFromJson(string jsonString)
        {
            using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonString)))
            {
                var ser = new DataContractJsonSerializer(typeof(OAuthToken));
                var oAuthToken = (OAuthToken)ser.ReadObject(ms);
                return oAuthToken;
            }
        }

        private OAuthToken GetAccessToken(string secret, string sid)
        {
            var urlEncodedSecret = HttpUtility.UrlEncode(secret);
            var urlEncodedSid = HttpUtility.UrlEncode(sid);

            var body = String.Format("grant_type=client_credentials&client_id={0}&client_secret={1}&scope=notify.windows.com",
                                     urlEncodedSid,
                                     urlEncodedSecret);

            string response;
            using (var client = new WebClient())
            {
                client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
                response = client.UploadString("https://login.live.com/accesstoken.srf", body);
            }
            return GetOAuthTokenFromJson(response);
        }

        public event EventHandler SendComplet;
        public event EventHandler<SendExceptionArgs> SendException;

        public void Dispose()
        {

        }
    }
}
